#pragma once

// Copyright (c) 2010 Manuel Peinado Gallego <manuel.peinado@gmail.com>
// Distributed under the MIT license

// PythonManager.h : interface of the PythonManager class
//

#include "BoostPython.h"


// ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-

// Declare a C++ class to simulate python stdio
// Take from here: http://bit.ly/ddLTAM

class PythonStdIoRedirect 
{
public:

    typedef boost::circular_buffer<std::string> ContainerType;

    void write(const std::string & str);

    static std::string getOutput();

private:

    static ContainerType m_outputs; // must be static, otherwise output is missing
};


// ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-


class PythonManager : boost::noncopyable
{
public:

    // ------------------------------------------------------------------------

    // Initializes the Python interpreter
    PythonManager();

    // Shuts down the Python interpreter
    ~PythonManager();

    // ------------------------------------------------------------------------
    
    bpy::object& getContext();

    // ------------------------------------------------------------------------

    // Returns true if an script is running
    bool isRunning() const;

	// Does nothing if a script is already running
    void runConcurrently(const std::string& script);

	// Does nothing if a script is not running
	void stopCurrentScript();

    // ------------------------------------------------------------------------
    // Non-const because it clears the ouput as well
    std::string getStdOutput();

    // ------------------------------------------------------------------------

private:

    // True if an script is running concurrently
    bool m_running;

    // The main module
    bpy::object m_mainModule;

    // The module where we place all our extensions
    bpy::object m_coreModule;

    // A dictionary for the main module. We will run our 
    // code inside this namespace
    bpy::object m_mainNamespace;

    // This object will capture the std. output from Python and
    // make it available as an std::string
    PythonStdIoRedirect m_pythonStdioRedirector;

    // --------------------------------------------------------------

    void initialize();
    bool m_initialized;

    // --------------------------------------------------------------
};

// ------------------------------------------------------------------
// Poor man's singleton pattern

inline PythonManager& pyManager()
{
    static PythonManager instance;
    return instance;
}


